package org.spp.voronoi;

import org.spp.utilities.Point;

import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math.util.MathUtils;


/**
 * Vertex.java
 * @author Ilio Catallo, Eleonora Ciceri
 * @version 1.0
 * 
 * Description: class that implements a vertex of the voronoi diagram
 * 
 * Date: Jul 10, 2011
 */
public abstract class Vertex extends Point {
    
    // Attributes
    protected List<Edge> edges;
    protected List<Cell> cells;
    protected double factor;
    
    /**
     * Constructor for the class Vertex
     * @param coordinates 
     */ 
    public Vertex(double[] coordinates) {
        
        super(coordinates);
        this.cells = new ArrayList<Cell>();
        this.edges = new ArrayList<Edge>();
        
        computeFactor();
    }
    
    /**
     * Constructor for the class Vertex
     * @param coordinates 
     */
    public Vertex(double[][] coordinates) {
        super(coordinates);
        cells = new ArrayList<Cell>();
        edges = new ArrayList<Edge>();
        
        computeFactor();
    }
    
     /**
     * Method that returns the list of outgoing edges from the current vertex
     * @return edges
     */
    public List<Edge> getEdges() {
        return edges;
    }
    
    /**
     * Method that returns all the cells that contain the current vertex
     * @return cells
     */
    public List<Cell> getCells() {
        return cells;
    }
    
     /**
     * Method that returns the factor of the vertex, e.g. how much percentage
     * of the hypersphere centered in the verte will be inside the bounded region
     * @return factor
     */
    public double getFactor(){
        return factor;
    }

    /**
     * Method that adds a cell to the list of cells that contain the current vertex
     * @param cell 
     */
    public void addCell(Cell cell) {
        cells.add(cell);
    }
    
    /**
     * Method that adds a edge to the list of outgoing edges from the current vertex
     * @param edge 
     */
    public void addEdge(Edge edge){
        edges.add(edge);
        
    }
     
    /**
     * Method that computes the outgoing edges from the vertex (to be implemented
     * by Vertex2D and Vertex3D)
     */
    public abstract void computeEdges();
    
    /**
     * Method that computes the factor for the vertex 
     */
    private void computeFactor(){
        // Variables
        int numMaxCoordinates = 0;
        
        for (int i = 0; i < coordinates.length; i++)
            if (Math.abs(Math.abs(coordinates[i]) - 0.5) < MathUtils.EPSILON)
                numMaxCoordinates++;
        
        if (numMaxCoordinates == 0)
            factor = 1;
        if (numMaxCoordinates == 1)
            factor = 0.5;
        if (numMaxCoordinates == 2)
            factor = 0.25;
        if (numMaxCoordinates == 3)
            factor = 0.125;
                
    }
    
}
